
#include <algorithm>

#include "undertopomgr.h"
#include "simulator.h"
#include "eventdefs.h"
#include "node.h"
#include "config.h"
#include "random.h"

UnderTopoMgr* UnderTopoMgr::instance_ = NULL;


UnderTopoMgr::~UnderTopoMgr()
{
	std::for_each( nodes_.begin(), nodes_.end(), ReleaseObject() );
	nodes_.clear();
}

bool UnderTopoMgr::create()
{
	NEW_OBJECT( UnderTopoMgr, instance_, () )
	return true;
}

bool UnderTopoMgr::init()
{
	switch( config.undertopo_.topo_source ){
		case Config::TOPO_STATIC:
			return createTopoStatic();
		case Config::TOPO_FILE:
			return createTopoFromFile();
		default:
			assert_or_retv( false, false );
	}
}

void UnderTopoMgr::destroy()
{
	if ( instance_!=NULL ){
		RELEASE_OBJ( instance_ );
	}
}

bool UnderTopoMgr::send( node_id_t src_id, node_id_t dst_id, Packet *packet )
{
	assert_or_retv( packet!=NULL, false );

	bool ret = false;
	Node *src_node = node(src_id);
	Node *dst_node = node(dst_id);

	if ( (src_node!=NULL) && (dst_node!=NULL) ){
		NEW_VAR_OBJECT2( Event, RecvPackEvent, event, (dst_node, packet) )
		Simulator::instance().scheduleEvent( event, latency(src_id,dst_id) );
		RELEASE_OBJ(event)
		ret = true;
	}

	return ret;

}

sim_time_t UnderTopoMgr::latency( node_id_t src_id, node_id_t dst_id )
{
	return 0.01;
}

Node* UnderTopoMgr::node( node_id_t id )
{
	if ( id>=0 && id<(node_id_t)nodes_.size() ){
		return nodes_[id];
	} else{
		return NULL;
	}
}

bool UnderTopoMgr::createTopoStatic()
{
	int network_size = config.undertopo_.network_size;
	assert_or_retv( network_size>0, false );

	for ( int id=0; id<network_size; id++ ){
		//TODO: create nodes here
	}
	return true;

}

bool UnderTopoMgr::createTopoFromFile()
{
	return false;
}
